package contents

import (
	"context"
	"fmt"
	"github.com/google/go-github/github"
	"github.com/prometheus/common/log"
	"img_bed/def"
	"img_bed/utils"
	"io/ioutil"
	"net/http"
	"os"
	"path/filepath"
	"strconv"
	"strings"
	"time"
)

type ImgBedContents struct {
	client *github.Client
	ctx    *context.Context
}

func New(client *github.Client, ctx *context.Context) *ImgBedContents {
	return &ImgBedContents{
		client: client,
		ctx:    ctx,
	}
}
func (this *ImgBedContents) GetAllFileInRootPath() (*[]github.TreeEntry, error) {
	sha, err := this.GetRootPathSha()
	if err != nil {
		log.Error("错误信息：%s", err.Error())
		return nil, err
	}
	log.Info("获取到图床根目录的sha为:%s", *sha)

	fileTrees, err := this.GetFileInPath(*sha)
	if err != nil {
		log.Error("错误信息：%s", err.Error())
		return nil, err
	}
	if fileTrees == nil || len(fileTrees.Entries) <= 0 {
		log.Error("查到的文件为空")
		return nil, err
	}
	return &fileTrees.Entries, nil
}

func (this *ImgBedContents) DownFile(url string, path string) {

	log.Info("下载文件的地址：%s", url)
	resp, _ := http.Get(url)

	fileBytes, _ := ioutil.ReadAll(resp.Body)

	tmpFileName := utils.GetFileNameByFullPath(url)
	log.Info("下载的文件名：%s", tmpFileName)

	localFile := utils.MergePathFile(path, tmpFileName)

	log.Info("下载到的位置：%s", localFile)

	os.Remove(localFile)
	os.Create(localFile)
	file, _ := os.OpenFile(localFile, os.O_RDWR, os.ModeAppend)
	defer file.Close()
	file.Write(fileBytes)
}

func (this *ImgBedContents) GetFileInPath(sha string) (*github.Tree, error) {
	tree, _, err := this.client.Git.GetTree(*this.ctx, def.OWNER, def.REPO, sha, false)
	if err != nil || tree == nil || len(tree.Entries) <= 0 {
		log.Error("查询目录树失败，指定的sha:%s", sha)
		return nil, err
	}
	log.Info("查询到目录树结构：sha:%s", sha)
	return tree, err
}

func (this *ImgBedContents) GetRootPathSha() (*string, error) {
	commits, _, err := this.client.Repositories.ListCommits(*this.ctx, def.OWNER, def.REPO, &github.CommitsListOptions{
		Path: def.PATH_NAME,
		ListOptions: github.ListOptions{
			Page:    1,
			PerPage: 1,
		},
	})
	if err != nil || len(commits) <= 0 {
		log.Error("查询最后一次提交记录失败")
		return nil, err
	}

	log.Info("最后一次提交记录的sha:%s", commits)

	tmpPaths := utils.SplitFullPath(def.PATH_NAME)
	tmpMaxIndex := len(tmpPaths)
	tmpIndex := 0
	tmpSHA := commits[0].GetSHA()

	for tmpIndex < tmpMaxIndex {
		tree, err := this.GetFileInPath(tmpSHA)
		if err != nil || tree == nil || len(tree.Entries) <= 0 {
			log.Error("查询目录树失败")
			return nil, err
		}
		entry, err := func(Entries *[]github.TreeEntry) (*github.TreeEntry, error) {
			for _, entry := range tree.Entries {
				if tmpPaths[tmpIndex] == entry.GetPath() {
					return &entry, nil
				}
			}
			return nil, &def.DefaultError{
				Msg: "目录" + tmpPaths[tmpIndex] + "不存在",
			}
		}(&tree.Entries)

		if err != nil {
			log.Error(err.Error())
			return nil, err
		}

		log.Info("第%d层目录匹配成功，目录名为：%s", tmpIndex+1, tmpPaths[tmpIndex])
		tmpIndex++
		tmpSHA = entry.GetSHA()
	}
	return &tmpSHA, nil
}

func (this *ImgBedContents) getContents() (*github.RepositoryContent, []*github.RepositoryContent) {
	file, files, _, _ := this.client.Repositories.GetContents(*this.ctx, def.OWNER, def.REPO, def.PATH_NAME, nil)
	return file, files
}

func (this *ImgBedContents) UploadContent(filePath *string) *string {

	newFileName, contentFile, _ := this.createUploadFileInfo(filePath)

	file, _, err := this.client.Repositories.CreateFile(*this.ctx, def.OWNER, def.REPO, def.PATH_NAME+newFileName, contentFile)
	if err != nil {
		fmt.Printf("上传图片错误:%s", err.Error())
		return nil
	}
	fmt.Println(file)
	s := file.GetURL()
	return &s
}

func (this *ImgBedContents) createUploadFileInfo(filePath *string) (string, *github.RepositoryContentFileOptions, error) {
	_, fileName := filepath.Split(*filePath)
	log.Info("根据上传文件路径获取到的文件名为：%s", fileName)
	fileNameSplit := strings.Split(fileName, ".")
	unixNano := time.Now().UnixNano()
	newFileName := fileNameSplit[0] + strconv.FormatInt(unixNano, 10) + "." + fileNameSplit[1]

	context, _ := ioutil.ReadFile(*filePath)
	message := "createFile_" + newFileName

	contentFile := github.RepositoryContentFileOptions{
		Message: &message,
		Content: context,
	}
	return newFileName, &contentFile, nil
}
